package com.itheima.bcript;


import org.mindrot.jbcrypt.BCrypt;

/**
 * BCrypt 加密工具类
 * 用于安全地对密码进行哈希处理（加盐加密）
 */
public class BCryptUtil {

    /**
     * 默认的哈希强度（工作因子），范围是 4-31
     * 数值越大，计算越慢，安全性越高
     * 12 是一个在安全性和性能之间比较平衡的常用值
     */
    private  final int DEFAULT_WORK_FACTOR = 12;

    /**
     * 使用默认强度对明文密码进行哈希（加盐加密）
     *
     * @param plainTextPassword 明文密码
     * @return 加盐并哈希后的密码字符串（包含盐值和哈希值）
     */
    public  String hashPassword(String plainTextPassword) {
        if (plainTextPassword == null) {
            throw new IllegalArgumentException("密码不能为空");
        }
        return BCrypt.hashpw(plainTextPassword, BCrypt.gensalt(DEFAULT_WORK_FACTOR));
    }

    /**
     * 使用指定的强度对明文密码进行哈希（加盐加密）
     *
     * @param plainTextPassword 明文密码
     * @param workFactor        哈希强度（工作因子），推荐值 10-14
     * @return 加盐并哈希后的密码字符串
     */
    public  String hashPassword(String plainTextPassword, int workFactor) {
        if (plainTextPassword == null) {
            throw new IllegalArgumentException("密码不能为空");
        }
        if (workFactor < 4 || workFactor > 31) {
            throw new IllegalArgumentException("工作因子必须在 4 到 31 之间");
        }
        return BCrypt.hashpw(plainTextPassword, BCrypt.gensalt(workFactor));
    }

    /**
     * 验证明文密码与存储的哈希值是否匹配
     *
     * @param plainTextPassword 明文密码
     * @param hashedPassword    存储的哈希密码（包含盐值）
     * @return 如果密码匹配返回 true，否则返回 false
     */
    public  boolean checkPassword(String plainTextPassword, String hashedPassword) {
        if (plainTextPassword == null || hashedPassword == null) {
            return false;
        }
        return BCrypt.checkpw(plainTextPassword, hashedPassword);
    }

    /**
     * 检查一个哈希密码是否是使用 BCrypt 算法生成的
     *
     * @param hashedPassword 哈希密码字符串
     * @return 如果是 BCrypt 格式返回 true
     */
    public  boolean isHashValid(String hashedPassword) {
        return hashedPassword != null &&
                hashedPassword.startsWith("$2a$") ||
                hashedPassword.startsWith("$2b$") ||
                hashedPassword.startsWith("$2y$");
    }

}